package xyz.zhuht.algorithm.medium;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * @author haitao zhu
 * @date 2020/7/9 17:50
 * 面试题17.13 回复空格
 * <p>
 * 哦，不！你不小心把一个长篇文章中的空格、标点都删掉了，并且大写也弄成了小写。像句子"I reset the computer. It still didn’t boot!"已经变成了"iresetthecomputeritstilldidntboot"。在处理标点符号和大小写之前，你得先把它断成词语。当然了，你有一本厚厚的词典dictionary，不过，有些词没在词典里。假设文章用sentence表示，设计一个算法，把文章断开，要求未识别的字符最少，返回未识别的字符数。
 * <p>
 * 注意：本题相对原题稍作改动，只需返回未识别的字符数
 * <p>
 *  
 * <p>
 * 示例：
 * <p>
 * 输入：
 * dictionary = ["looked","just","like","her","brother"]
 * sentence = "jesslookedjustliketimherbrother"
 * 输出： 7
 * 解释： 断句后为"jess looked just like tim her brother"，共7个未识别字符。
 * 提示：
 * <p>
 * 0 <= len(sentence) <= 1000
 * dictionary中总字符数不超过 150000。
 * 你可以认为dictionary和sentence中只包含小写字母。
 * <p>
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode-cn.com/problems/re-space-lcci
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 */
public class HuiFuKongGe {
  static final long P = Integer.MAX_VALUE;
  static final long BASE = 41;

  public int respace(String[] dictionary, String sentence) {
    Set<Long> hashValues = new HashSet<Long>();
    for (String word : dictionary) {
      hashValues.add(getHash(word));
    }

    int[] f = new int[sentence.length() + 1];
    Arrays.fill(f, sentence.length());

    f[0] = 0;
    for (int i = 1; i <= sentence.length(); ++i) {
      f[i] = f[i - 1] + 1;
      long hashValue = 0;
      for (int j = i; j >= 1; --j) {
        int t = sentence.charAt(j - 1) - 'a' + 1;
        hashValue = (hashValue * BASE + t) % P;
        if (hashValues.contains(hashValue)) {
          f[i] = Math.min(f[i], f[j - 1]);
        }
      }
    }

    return f[sentence.length()];
  }

  public long getHash(String s) {
    long hashValue = 0;
    for (int i = s.length() - 1; i >= 0; --i) {
      hashValue = (hashValue * BASE + s.charAt(i) - 'a' + 1) % P;
    }
    return hashValue;
  }
}

